<?php
// 对页面业务逻辑封装
define("DUANURL_DEFAULT_LEN", 4); //默认初始token字符串长度
define("DUANURL_GENERATED_BY_SYSTEM", 0x01); //通过系统生成的token
define("DUANURL_USER_ASSIGNED_TOKEN", 0x02); // 用户指定的 token
define("DUANURL_DUPLICATED_TOKEN", 0x03); // 重复的token
define("DUANURL_DB_ERROR", 0x04); //数据库错误
define("DUANURL_URL_INVALID_URL", 0x05); //非法的url格式
define("DUANURL_UNKNOWN_ERROR", 0x06); // 未知错误
 
class Facade
{
    // 使用默认的算法生成最新的token
    public static function genToken($realurl, $len = DUANURL_DEFAULT_LEN, $token_type = TokenType::DUANURL_TT_DEFAULT)
    {
        // 先判断是否已经存在token
        $mdao = new MappingDAO();

        // 进行锁表
        if ($mdao->sql("LOCK TABLE mapping WRITE, stats READ"))
        {
            // 锁定成功
            error_log("Locked table mapping");

        };
        $vo = $mdao->produceVO();
        $vo->set('realurl', $realurl);
        $result = $mdao->getByCol(array('realurl'), array($vo));
        foreach ($result as $row)
        {
            $token = $row->get('token');
            if (strlen($token) <= (DUANURL_DEFAULT_LEN+1))
            {
                $mdao->sql("UNLOCK TABLES"); // 解除锁定

                return array('token' => $token,
                    'realurl' => $realurl,
                    'dup' => true,
                    'error' => false,
                    'code' => DUANURL_DUPLICATED_TOKEN
                );
            }
        }


        // 先获取上次更新的token
        $dao = new StatsDAO();
        $vo = $dao->produceVO();
        $vo->set('skey', 'last_updated_token');
        $result = $dao->getByCol(array('skey'), array($vo));
        if (empty($result))
        {
            $last_updated_token = null;
        }
        else
        {
            $last_updated_token = $result[0]->get('svalue');
            if (empty ($last_updated_token)) $last_updated_token = null;
        }

        $hash = new DuanUrlHash();
        $token = '';

        // 生成 key, 直到不与现有数据冲突
        $continue =true;
        while ($continue)
        {
            $token = $hash->getNextHash( $last_updated_token );
            $vo = $mdao->produceVO();
            $vo->set('token', $token);
            $result = $mdao->getByCol( array('token'), array($vo));
            if (empty($result))
            {
                // 添加mapping表记录
                $continue = false;
                $vo->set('realurl', $realurl);
                $vo->set('token_length', strlen($token));
                $vo->set('realurl_length', strlen($realurl));
                $vo->set('update_time', time());
                $vo->set('create_time', time());
                $vo->set('update_ip', null);
                $vo->set('token_type', $token_type);
                $mdao->add($vo);

                $mdao->sql("UNLOCK TABLES"); // 解除锁定
                // 更新状态表
                $vo = $dao->produceVO();
                $vo->set('skey', 'last_updated_token');
                $vo->set('svalue', $token);
                $vo->set('updated_time', time());
                $dao->replace($vo);
            }
            else
            {
                $last_updated_token = $token;
                $continue = true;
            }
        }
        
        $mdao->sql("UNLOCK TABLES"); // 解除锁定
        return array('token' => $token,
            'realurl' => $realurl,
            'dup' => false,
            'error' => false,
            'code' => DUANURL_GENERATED_BY_SYSTEM
        );

    }

    // 使用custom推荐的token进行生成
    public static function genTokenWithToken( $realurl, $token , $len = DUANURL_DEFAULT_LEN, $token_type = TokenType::DUANURL_TT_DEFAULT)
    {
        // 先判断是否已经存在token和 realurl的对应
        $mdao = new MappingDAO();
        $vo = $mdao->produceVO();
        $vo->set('token', $token);
        $result = $mdao->getByCol(array('token'), array($vo));
        if (empty($result))
        {
            $vo->set('realurl', $realurl);
            $vo->set('token_length', strlen($token));
            $vo->set('realurl_length', strlen($realurl));
            $vo->set('update_time', time());
            $vo->set('create_time', time());
            $vo->set('update_ip', null);
            $vo->set('token_type', $token_type);
            $mdao->add($vo);
            return array('realurl' => $realurl,
                         'token' => $token,
                         'dup' => false,
                         'error' => false,
                         'code' => DUANURL_USER_ASSIGNED_TOKEN
                     );
        }
        else
        {
            $ru = $result[0]->get('realurl');
            if ($ru == $realurl )
            {
                return array('token' => $token,
                    'realurl' => $realurl,
                    'dup' => true,
                    'error' => false,
                    'code' => DUANURL_DUPLICATED_TOKEN
                );
            }
            else
            {
                return self::genToken($realurl, $len);
            }
        }
    }

    // 通过token 获取url的信息
    /*
array(1) {
  [0]=>
  object(Mapping)#6 (3) {
    ["allows:protected"]=>
    array(8) {
      [0]=>
      string(5) "token"
      [1]=>
      string(7) "realurl"
      [2]=>
      string(12) "token_length"
      [3]=>
      string(14) "realurl_length"
      [4]=>
      string(11) "update_time"
      [5]=>
      string(11) "create_time"
      [6]=>
      string(9) "update_ip"
      [7]=>
      string(9) "create_ip"
    }
    ["entity:protected"]=>
    array(9) {
      ["token"]=>
      string(6) "abcdef"
      ["realurl"]=>
      string(22) "http://rainx.cn/test81"
      ["token_length"]=>
      string(1) "6"
      ["realurl_length"]=>
      string(2) "22"
      ["update_time"]=>
      string(10) "1232441128"
      ["create_time"]=>
      string(10) "1232441128"
      ["create_ip"]=>
      NULL
      ["update_ip"]=>
      NULL
      ["token_type"]=>
      string(1) "0"
    }
    ["logger:protected"]=>
    object(Logger)#3 (0) {
    }
  }
}
     */
    public static function getUrlInfoByToken($token)
    {
        $mdao = new MappingDAO();
        $vo = $mdao->produceVO();
        $vo->set('token', $token);
        $result = $mdao->getByCol(array('token'), array($vo));
        if (empty($result))
        {
            return false;
        }
        else
            return $result[0];
    }
}

?>
